﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using BluEtch.GotPhone.Helpers;
using System.Collections.ObjectModel;

namespace BluEtch.GotPhone.Data
{
    public class IsolatedJSON
    {
        private string _baseDirectory;
        private const string _extension = "json";

        /// <summary>
        /// Constructor ensures that the directory used has been created.
        /// </summary>
        /// <param name="baseDirectory">Overridable base directory, useful for backups, etc.</param>
        public IsolatedJSON(string baseDirectory = "JSON")
        {
            // Override base directory if desired
            _baseDirectory = baseDirectory;

            // Attempt to create the directory if it doesn't exist
            IsolatedFileStorage.CreateDirectory(_baseDirectory);
        }

        /// <summary>
        /// Retrieves a single object stored in a file in the current application's Isolated Storage.
        /// Retrieves the object based off the object's class name.
        /// </summary>
        /// <typeparam name="T">Type of object to be retrieved (can be inferred)</typeparam>
        /// <param name="defaultValue">Default value to be overriden if desired</param>
        /// <returns>Object from storage or default value</returns>
        public T Retrieve<T>(T defaultValue = default(T))
        {
            T results = defaultValue;

            var contents = IsolatedFileStorage.ReadFile(_baseDirectory, _GetFilePath<T>());

            if (contents != null)
            {
                results = Serialization.Deserialize<T>(contents);
            }

            return results;
        }

        /// <summary>
        /// Retrieves a single object stored in a file in the current application's Isolated Storage.
        /// Retrieves the object based off a specified file name, as opposed to the object's class name.
        /// </summary>
        /// <typeparam name="T">Type of object to be retrieved (can be inferred)</typeparam>
        /// <param name="fileName">Name of file to be retrieved and parsed into an object</param>
        /// <param name="defaultValue">Default value to be overriden if desired</param>
        /// <returns>Object from storage or default value</returns>
        public T Retrieve<T>(string fileName, T defaultValue = default(T))
        {
            T results = defaultValue;

            var contents = IsolatedFileStorage.ReadFile(_baseDirectory, _GetFilePath(fileName));

            if (contents != null)
            {
                results = Serialization.Deserialize<T>(contents);
            }

            return results;
        }

        /// <summary>
        /// Retrieves a collection of items from isolated storage based of the class name of type specified.
        /// </summary>
        /// <typeparam name="T">Type of object to be retrieved</typeparam>
        /// <returns>List of objects, or empty list</returns>
        public List<T> RetrieveCollection<T>()
        {
            List<T> results = new List<T>();

            var contents = IsolatedFileStorage.ReadFile(_baseDirectory, _GetFilePath<T>());

            if (contents != null)
            {
                results = Serialization.Deserialize<List<T>>(contents);
            }

            return results;
        }

        /// <summary>
        /// Retrieves a collection of items from isolated storage based of the file name specified.
        /// </summary>
        /// <typeparam name="T">Type of object to be retrieved</typeparam>
        /// <param name="fileName">Name of file to be retrieved</param>
        /// <returns>List of objects, or empty list</returns>
        public List<T> RetrieveCollection<T>(string fileName)
        {
            List<T> results = new List<T>();

            var contents = IsolatedFileStorage.ReadFile(_baseDirectory, _GetFilePath(fileName));

            if (contents != null)
            {
                results = Serialization.Deserialize<List<T>>(contents);
            }

            return results;
        }

        /// <summary>
        /// Stores an object in Isolated File Storage as a JSON string in a file using the class name
        /// as the name of the file.
        /// </summary>
        /// <typeparam name="T">Type of object to be stored</typeparam>
        /// <param name="obj"></param>
        public void Store<T>(T obj)
        {
            if (obj != null)
            {
                var contents = Serialization.Serialize(obj);

                IsolatedFileStorage.CreateFile(_baseDirectory, _GetFilePath<T>(), contents, true);
            }
        }

        /// <summary>
        /// Stores an object in Isolated File Storage as a JSON string in a file using the
        /// specified file name as the name of the file.
        /// </summary>
        /// <typeparam name="T">Type of object to be stored, can be inferred</typeparam>
        /// <param name="fileName">Name of the file to be stored</param>
        /// <param name="obj">Object to be stored in the file</param>
        public void Store<T>(string fileName, T obj)
        {
            if (obj != null)
            {
                var contents = Serialization.Serialize(obj);

                IsolatedFileStorage.CreateFile(_baseDirectory, _GetFilePath<T>(), contents, true);
            }
        }

        /// <summary>
        /// Stores a collection of objects in Isolated File Storage as a JSON string in a file using the
        /// class name as the name of the file.
        /// </summary>
        /// <typeparam name="T">Type of object to be stored, can be inferred</typeparam>
        /// <param name="objects">Objects to be stored in the file</param>
        public void StoreCollection<T>(List<T> objects)
        {
            if (objects != null && objects.Count > 0)
            {
                var contents = Serialization.Serialize(objects);

                IsolatedFileStorage.CreateFile(_baseDirectory, _GetFilePath<T>(), contents, true);
            }
        }

        /// <summary>
        /// Stores a collection of objects in Isolated File Storage as a JSON string in a file using the
        /// specified file name as the name of the file.
        /// </summary>
        /// <typeparam name="T">Type of object to be stored, can be inferred</typeparam>
        /// <param name="fileName">Name of the file to be stored</param>
        /// <param name="objects">Objects to be stored in the file</param>
        public void StoreCollection<T>(string fileName, List<T> objects)
        {
            if (objects != null && objects.Count > 0)
            {
                var contents = Serialization.Serialize(objects);

                IsolatedFileStorage.CreateFile(_baseDirectory, _GetFilePath<T>(), contents, true);
            }
        }

        /// <summary>
        /// Gets the file name to be used for storage based off a type name
        /// </summary>
        /// <typeparam name="T">Type to use as file name</typeparam>
        /// <returns>file name with extension</returns>
        private string _GetFilePath<T>()
        {
            return _GetFilePath(typeof(T).Name);
        }

        /// <summary>
        /// Gets the file name to be used for storage based off a specified name
        /// </summary>
        /// <param name="fileName">Name to use as file name</param>
        /// <returns>file name with extension</returns>
        private string _GetFilePath(string fileName)
        {
            return string.Format("{0}.{1}", fileName, _extension);
        }
    }
}
